<?php

require_once("functionobject.php");

$__GCOUNT = 0;

class Environment {

    var $e = array();
    var $parent = null;
    var $level = null;
    var $class_id = null;

    function Environment($parent=null, $bindings=null) {
        global $__GCOUNT;

        $__GCOUNT = $__GCOUNT + 1;
        $this->class_id = $__GCOUNT;

        if ($bindings) {
            $this->e = $bindings;
        } else {
            $this->e = array();
        }
        $this->parent = $parent;
        if ($this->parent) {
            $this->level = $this->parent->level + 1;
        } else {
            $this->level = 0;
        }
        $this->init();
    }

    function init() {
        
    }

    function set($sym, $value) {
        if (isset($this->e[$sym])) {
            $this->e[$sym] = $value;
        } elseif ($this->parent) {
            $this->parent->set($sym, $value);
        } else {
            $this->e[$sym] = $value;
        }
    }

    function lexical_set($sym, $value) {

        $this->e[$sym] = $value;
    }

    function get($sym) {

        if (!isset($this->e[$sym])) {

            if ($this->parent) {
                return $this->parent->get($sym);
            } else {
                echo "Unbound Symbol Error, $sym";
                exit();
            }
        } else {
            return $this->e[$sym];
        }
    }

    function push($bindings=null) {
        return new Environment($this, $bindings);
    }

    function pop() {
        return $this->parent;
    }

    function repr() {
        $s = "\nLevel " . $this->level . ":\n";
        foreach ($this->e as $key => $val) {
            if ($key != "*env*") {
                $s .= " $key: $val\n";
            }
        }
        if ($this->parent) {
            return $s . $this->parent->repr();
        } else {
            return $s;
        }
    }

    function nullp() {
        return new LogicObject(0);
    }

}